package com.example.service.impl;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.example.aop.MyLog;
import com.example.dao.EncryptMapper;
import com.example.dao.UserMapper;
import com.example.entity.User;
import com.example.service.UserService;
import com.example.utils.pinYin.pinYinUtil;
import com.example.utils.randomData;
import com.example.utils.security.Md5Utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EncryptMapper encryptMapper;

    @Override
    public int insertUser(User user) {
        String phone = encrypt(user.getPhone());
        user.setPhone(phone);
        String phoneKeywords = phoneKeywords(user.getPhone());
        encryptMapper.insertPhoneKeyWords(String.valueOf(user.getId()), phoneKeywords);
        return userMapper.insertUser(user);
    }

    @MyLog(value = "查询单个用户")  //这里添加了AOP的自定义注解
    @Override
    public User selectUserById(String id) {
        User user = userMapper.selectUserById(id);
        user.setPhone(decrypt(user.getPhone()));
        return user;
    }

    @Override
    public List<User> selectUserByParams(Map<String, Object> param) {
        return userMapper.selectUserByParams(param);
    }

    @Override
    @Async("taskExecutor")
    public String importUserList() {
        System.out.println(Thread.currentThread().getName() + "-----");
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        return "导入成功";
    }

    @Override
//    @Async("taskExecutor")
    public List<User> queryUserByPage(Map<String, Object> param) {
        System.out.println(Thread.currentThread().getName() + "-----");
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return userMapper.selectUserList(param);
    }

    /**
     * 分批次批量插入
     *
     * @throws IOException
     */
    @Override
    public int batchInsertUser(int num) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession session = sqlSessionFactory.openSession();
        try {
            List<User> userList = new ArrayList<>();
            for (int i = 1; i <= num; i++) {
                User user = new User();
                String name = randomData.getName();
                user.setId(randomData.uniqueValueId());
                user.setUsername(pinYinUtil.getPinYinAllChar(name, false));
                user.setPassword(Md5Utils.hash("123456"));
                user.setActName(name);
                user.setEmail(randomData.getEmail(16, 22));
                user.setPhone(randomData.getTel());
                user.setStatus('1');
                user.setRole('0');
                userList.add(user);
                if (i % 1000 == 0) {
                    session.insert("batchInsertUser", userList);
                    // 每 1000 条数据提交一次事务
                    session.commit();
                    userList.clear();
                }
            }
            // 最后插入剩余的数据
            if (!CollectionUtils.isEmpty(userList)) {
                session.insert("batchInsertUser", userList);
                session.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            session.close();
        }
        return num;
    }

    private String phoneKeywords(String phone) {
        String keywords = this.keywords(phone, 4);
        System.out.println(keywords.length());
        return keywords;
    }

    //分词组合加密
    private String keywords(String word, int len) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < word.length(); i++) {
            int start = i;
            int end = i + len;
            String sub1 = word.substring(start, end);
            sb.append(this.encrypt(sub1));
            if (end == word.length()) {
                break;
            }
        }
        return sb.toString();
    }

    public String encrypt(String val) {
        //这里特别注意一下，对称加密是根据密钥进行加密和解密的，加密和解密的密钥是相同的，一旦泄漏，就无秘密可言，
        //“fanfu-csdn”就是我自定义的密钥，这里仅作演示使用，实际业务中，这个密钥要以安全的方式存储；
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), "fanfu-csdn".getBytes()).getEncoded();
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
        String encryptValue = aes.encryptBase64(val);
        return encryptValue;
    }

    public String decrypt(String val) {
        //这里特别注意一下，对称加密是根据密钥进行加密和解密的，加密和解密的密钥是相同的，一旦泄漏，就无秘密可言，
        //“fanfu-csdn”就是我自定义的密钥，这里仅作演示使用，实际业务中，这个密钥要以安全的方式存储；
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), "fanfu-csdn".getBytes()).getEncoded();
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
        String encryptValue = aes.decryptStr(val);
        return encryptValue;
    }
}
